#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mg_Rotate.h"
#include "mg_pwm.h"
#include "mg_TLC59116.h"
#include "mg_Device.h"
#include "mg_Gesture.h"
#define EXPECTED_CNT 360 
#define ORIGINAL_CNT 446

MOVE_STATE Rotate;//传感器参数（全局）
static uint16_t BlockNum_Circle;
static uint16_t Bee_Interval_Scale;
//毫秒级延时（非阻塞）
void Rotate_Delay_Ms(uint32_t ms)
{
	usleep(1000 * ms);
}
//PAT9125写一个字节数据
uint8_t RT_Write_Byte(uint8_t RT_Address, uint8_t RT_data)
{
	I2C2_Write_Reg(PAT9125_ADDR, RT_Address, &RT_data, 1);
}
//PAT9125读一个字节数据
uint8_t RT_Read_Byte(uint8_t RT_Address)
{
	return I2C2_Read_Reg(PAT9125_ADDR, RT_Address);
}
//在=指定地址开始读出长度为Len的数据
//该函数用于读出16bit或者32bit的数据.
//ReadAddr   :开始读出的地址 
//返回值     :数据
//Len        :要读出数据的长度2,4
uint32_t RT_RegRead(uint8_t ReadAddr, uint8_t Len)
{
	uint8_t t;
	uint8_t val = 0;
	uint32_t temp = 0;

	for (t = 0; t<Len; t++)
	{
		temp <<= 8;
		val = RT_Read_Byte(ReadAddr + Len - t - 1);
		temp += val;
	}
	return temp;
}
//=================================================================================================
// 传感器寄存器写然后读命令. 
// 写命令后面跟着读命令是为了确保建议的设置被正确地编写. 
//================================================================================================= 
void RT_RegWriteRead(uint8_t address, uint8_t wdata)
{
	uint8_t rdata;
	do
	{
		RT_Write_Byte(address, wdata);//将数据写入指定地址
		rdata = RT_Read_Byte(address);//回读之前写的数据
	} while (rdata != wdata);//检查数据是否正确写入
	return;
}
//================================================================================================= 
// 传感器寄存器设置初始化过程. 
// 1. In RT_RegWriteRead() function, a write command followed by a read command is to ensure the recommended 
// settings are written correctly. 
// 2. Address 0x7F is write-only. A read to address 0x7F will always return a zero. 
//=================================================================================================
bool RT_Sensor_Init(void)
{
	unsigned char sensor_pid = 0, read_id_ok = 0;
	//读取地址0x00中的sensor_pid来检查串行链接是否有效，读取值应该是0x31.
	sensor_pid = RT_Read_Byte(0x00);
	if (sensor_pid == 0x31)
	{
		read_id_ok = 1;
		printf("Moorgen INFO:Found Rotate sensor PAT9125\n");
		//PAT9125传感器推荐设置:
		RT_Write_Byte(0x7F, 0x00); // 切换到bank0，不允许执行 RT_RegWriteRead 
		RT_Write_Byte(0x06, 0x97); // 软件重置(i.e. set bit7 to 1).不允许执行 RT_RegWriteRead
		// 因为这个位会自动清除为0。 
		Rotate_Delay_Ms(1); // delay 1ms 
		RT_Write_Byte(0x06, 0x17); //确保传感器处于复位状态。

		RT_RegWriteRead(0x09, 0x5A);//禁用写保护
		RT_RegWriteRead(0x0D, 0x65);//设置x轴分辨率(取决于应用程序) 
		RT_RegWriteRead(0x0E, 0xFF);//设置y轴分辨率(取决于应用程序)
		RT_RegWriteRead(0x19, 0x04);//设置12位X/Y数据格式(取决于应用程序)
		//RT_RegWriteRead(0x4B, 0x04);//仅适用于VDD=VDDA=1.7~1.9V:用于节电
		RT_RegWriteRead(0x09, 0x00);//启用写保护

		ithGpioSetMode(ROTATE_INT_Pin, ITH_GPIO_MODE0); //设定GPIO模式0
		ithGpioSetIn(ROTATE_INT_Pin); //设定为输入
		ithGpioCtrlEnable(ROTATE_INT_Pin, ITH_GPIO_PULL_ENABLE);
		ithGpioCtrlEnable(ROTATE_INT_Pin, ITH_GPIO_PULL_UP);
		ithGpioEnable(ROTATE_INT_Pin); //使能此IO
		printf("Moorgen INFO:Rotate sensor PAT9125 init succeed!\n");
	}
	else
	{
		printf("Moorgen INFO:Do not found Rotate sensor PAT9125\n");
	}
	Set_Rotate_Block(60);
	return read_id_ok;
}
//================================================================================================= 
// This function (Resolution Downscale) provides a more flexible software method for downscaling the resolution 
// generated by the hardware built-in method. 
// 1. Input data will be accumulated then scaled down. 
// 2. Downscale factors (EXPECTED_CNT, ORIGINAL_CNT) should be pre-defined to fit the requirements of the application. 
//================================================================================================= 
int16_t RT_ResDownscale(int16_t dCnt, int32_t *sum)
{
	*sum += dCnt;
	return (*sum * EXPECTED_CNT / ORIGINAL_CNT);//返回一个缩小的值
}
//================================================================================================= 
// 1. Read the Motion bit (bit7 in address 0x02) to check if the motion data of X/Y are available to read. 
// 2. If Motion bit=1, read X/Y motion data in address 0x03, 0x04 and 0x12. 
// 3. The 12-bit X/Y motion data are in 2’s compliment format and range from -2048 to +2047 
//================================================================================================= 
void RT_Sensor_ReadMotion(int16_t *dx, int16_t *dy)
{
	int16_t deltaX_l = 0, deltaY_l = 0, deltaXY_h = 0;
	int16_t deltaX_h = 0, deltaY_h = 0;
	//检查运动,数据位在第7位
	if (RT_RegRead(0x02, 1) & 0x80) 
	{
		Gesture_Timer_Reset();
		deltaX_l = RT_RegRead(0x03, 1);
		deltaY_l = RT_RegRead(0x04, 1);
		deltaXY_h = RT_RegRead(0x12, 1);

		deltaX_h = (deltaXY_h << 4) & 0xF00;
		if (deltaX_h & 0x800) deltaX_h |= 0xf000;

		deltaY_h = (deltaXY_h << 8) & 0xF00;
		if (deltaY_h & 0x800) deltaY_h |= 0xf000;
	}
	else
	{
		return;
	}
	//inverse X and/or Y if necessary 
	//*dx = -(deltaX_h | deltaX_l);
	*dx = deltaX_h | deltaX_l;
	//*dy = -(deltaY_h | deltaY_l);
	*dy = deltaY_h | deltaY_l;

	//赋值有用信息到全局
	Rotate.X_Place += *dx;//X位置更新
	Rotate.X_NPlace += *dx;
	//超过1圈,归0
	if (Rotate.X_Place >= ONE_ROUND_X_NUM)
		Rotate.X_Place -= ONE_ROUND_X_NUM;
	else if (Rotate.X_Place <= -(ONE_ROUND_X_NUM))
		Rotate.X_Place += ONE_ROUND_X_NUM;
	//超过2圈不回0
	if (Rotate.X_NPlace >= 2*ONE_ROUND_X_NUM)
		Clear_Rotate_Block();
	else if (Rotate.X_NPlace <= -(2 * ONE_ROUND_X_NUM))
		Clear_Rotate_Block();
	//printf("Rotate sensor PAT9125 X_Place:%d\n", Rotate.X_Place);
}
//设置旋转挡位的位移差，一圈3000，如设置60，一圈就会有50挡
static int32_t Scale_Interval, Scale_Interval_L;
static int32_t X_Place_L;

//位移清零
void Clear_Rotate_Block(void)
{
	Rotate.X_Place = 0;
	X_Place_L = 0;
	Rotate.X_NPlace = 0;
	Scale_Interval = 0;
	Scale_Interval_L = 0;
}
void Set_Rotate_Block(uint16_t Interval)
{
	BlockNum_Circle = Interval;//一圈的挡位数量
	Bee_Interval_Scale = ONE_ROUND_X_NUM / Interval;//一个挡位的位移变化值
	Clear_Rotate_Block();
}

//处理旋转数据
void Rotate_Progress(void)
{
	uint16_t LEDCircle_Angle;
	Scale_Interval = Rotate.X_NPlace / BlockNum_Circle;//Scale_Interval变量：挡位间隔决定大小
	//LED根据角度变化
	if ((Rotate.Move_X > 1 || Rotate.Move_X < -1) && (Rotate.X_Place != X_Place_L))//稍微滤一下
	{
		if (Rotate.X_Place > 0)
			LEDCircle_Angle = Rotate.X_Place * 360 / ONE_ROUND_X_NUM;//转换角度
		else
			LEDCircle_Angle = (ONE_ROUND_X_NUM + Rotate.X_Place) * 360 / ONE_ROUND_X_NUM;//转换角度
		LED_Progress_Bar(LEDCircle_Angle);
		printf("LEDCircle_Angle = %d\n", LEDCircle_Angle);
		X_Place_L = Rotate.X_Place;
	}
	//挡位位子有变化
	if (Scale_Interval_L != Scale_Interval)
	{
		//转化为LCD事件
		ScreenSaverRefresh();//退出屏保
		if (Scale_Interval_L > Scale_Interval)
		{
			Action_Cmd.User_Action = Anticlockwise_Rotation;
			Action_Cmd.Action_Times = Scale_Interval_L - Scale_Interval;
		}
		else
		{
			Action_Cmd.User_Action = Clockwise_Rotation;
			Action_Cmd.Action_Times = Scale_Interval - Scale_Interval_L;
		}
		Bee_Di();//蜂鸣器“哒”
		printf("Moorgen INFO:Rotate Sensor X_Place : %d\n", Scale_Interval);
		Scale_Interval_L = Scale_Interval;
	}
}
//传感器实时检测
void RT_Sensor_Check(void)
{
	RT_Sensor_ReadMotion(&Rotate.Move_X, &Rotate.Move_Y);//读取旋转传感器
	if (Sys_Config.byte.Panal_EN == 0x01)//面板启用
	{
		Rotate_Progress();
	}
	else
	{
		Clear_Rotate_Block();
	}
}
